<!DOCTYPE html>
<!--
 Copyright 2022 Google LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{.App}} - Status</title>
  <script src="https://cdn.jsdelivr.net/npm/cytoscape@3.23.0/dist/cytoscape.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/dagre@0.8.5/dist/dagre.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre@2.5.0/cytoscape-dagre.min.js"></script>
  <script src="/assets/copy.js"></script>
  <link href="/assets/main.css" rel="stylesheet" />
  <!-- https://css-tricks.com/emoji-as-a-favicon/ -->
  <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🧶</text></svg>">
  <style>
    /* Style for the app table. */
    #apps td:nth-child(2) {
      border-left: 1px solid black;
    }

    /* Style for the components table. */
    #components th {
      text-align: left;
    }

    /* Style for the metrics table. */
    #metrics {
      font-family: "Roboto Mono",Consolas,monospace;
      font-size: small;
    }
    #metrics td, #metrics th{
      border: 0pt;
      padding: 4px 1ch;
    }
    #metrics td:nth-child(-n+1) {
      text-align: left;
    }
    #metrics td:nth-child(n+2) {
      text-align: right;
      padding-right: 1ex;
    }
    #metrics tr:nth-child(1) th:nth-child(n+2) {
      border-left: 1pt solid #E7E7E7;
    }
    #metrics th:nth-child(3n+2) {
      border-left: 1pt solid #E7E7E7;
    }
    #metrics td:nth-child(3n+2) {
      border-left: 1pt solid #E7E7E7;
    }

    /* Style for the traffic graph. */
    #traffic {
      width: 100%;
      height: 500px;
      border: 1pt solid black;
    }
  </style>
</head>

<body>
  <header class="navbar">
    <a href="/">{{.Tool}} dashboard</a>
  </header>

  <div class="container">
    <details open class="card" style="width: 49%">
      <summary class="card-title">Summary</summary>
      <div class="card-body">
        <table class="kv-table">
          <tr>
            <th scope="row">App</th>
            <td>{{.App}}</td>
          </tr>
          <tr>
            <th scope="row">Deployment</th>
            <td>{{.DeploymentId}}</td>
          </tr>
          <tr>
            <th scope="row">Age</th>
            <td>{{age .SubmissionTime}}</td>
          </tr>
          {{ range .Listeners}}
          <tr>
            <th scope="row">Listener "{{.Name}}"</th>
            <td>{{.Addr}}</td>
          </tr>
          {{ end }}
        </table>
      </div>
    </details>

    <div style="width: 49%">
      <details open class="card">
        <summary class="card-title">Links</summary>
        <div class="card-body">
          <ul>
            <li><a href="metrics?id={{.DeploymentId}}">Metrics</a></li>
            <li><a href="traces?id={{.DeploymentId}}">Traces</a></li>
          </ul>
        </div>
      </details>

      {{if len .Config.Sections}}
      <details class="card">
        <summary class="card-title">Config</summary>
        <div class="card-body">
          <pre>{{range $k, $v := .Config.Sections}}
[{{$k}}]
{{$v}}{{end}}</pre>
        </div>
      </details>
      {{end}}
    </div>

    <details class="card">
      <summary class="card-title">Commands</summary>
      <div class="card-body">
        <table class="kv-table">
          {{range .Commands}}
            <tr>
              <th scope="row">{{.Label}}</th>
              <td class="copyable"><code>{{.Command}}</code></td>
            </tr>
          {{end}}
        </table>
      </div>
    </details>


    <details open class="card">
      <summary class="card-title">Components</summary>
      <div class="card-body">
        <table id="components" class="data-table">
          <thead>
            <tr>
              <th>Component</th>
              <th>Replication</th>
              <th>PIDs</th>
            </tr>
          </thead>
          <tbody>
            {{range $c := .Components}}
            <tr>
              <td>{{shorten $c.Name}}</td>
              <td>{{len $c.Pids}}</td>
              <td>{{pidjoin $c.Pids}}</td>
            </tr>
            {{end}}
          </tbody>
        </table>
      </div>
    </details>

    <details open class="card">
      <summary class="card-title">Methods</summary>
      <div class="card-body">
        <table id="metrics" class="data-table">
          <tr>
            <th colspan=1></th>
            <th colspan=3>Count</th>
            <th colspan=3>Latency (ms)</th>
            <th colspan=3>Request (KB/s)</th>
            <th colspan=3>Reply (KB/s)</th>
          </tr>
          <tr>
            <th>Method</th>
            <th>Min.</th><th>Hr.</th><th>All</th>
            <th>Min.</th><th>Hr.</th><th>All</th>
            <th>Min.</th><th>Hr.</th><th>All</th>
            <th>Min.</th><th>Hr.</th><th>All</th>
          </tr>

          {{ range $c := .Components }}
            {{ range $c.Methods}}
            <tr>
              <td>{{ (shorten $c.Name) }}.{{ .Name }}</td>
              <td>{{ .Minute.NumCalls }}</td>
              <td>{{ .Hour.NumCalls }}</td>
              <td>{{ .Total.NumCalls }}</td>
              <td>{{ printf "%.4f" .Minute.AvgLatencyMs }}</td>
              <td>{{ printf "%.4f" .Hour.AvgLatencyMs }}</td>
              <td>{{ printf "%.4f" .Total.AvgLatencyMs }}</td>
              <td>{{ printf "%.2f" .Minute.RecvKbPerSec }}</td>
              <td>{{ printf "%.2f" .Hour.RecvKbPerSec }}</td>
              <td>{{ printf "%.2f" .Total.RecvKbPerSec }}</td>
              <td>{{ printf "%.2f" .Minute.SentKbPerSec }}</td>
              <td>{{ printf "%.2f" .Hour.SentKbPerSec }}</td>
              <td>{{ printf "%.2f" .Total.SentKbPerSec }}</td>
            </tr>
            {{ end }}
          {{ end }}
        </table>
      </div>
    </details>

    <details open class="card">
      <summary class="card-title">Traffic</summary>
      <div class="card-body">
        <div id="traffic"></div>
      </div>
    </details>

    <script>
      let total_value = 0;
      {{range .Traffic}}
        total_value += {{.Value}};
      {{end}}

      let colors = [
        "#4e79a7",
        "#f28e2c",
        "#e15759",
        "#76b7b2",
        "#59a14f",
        "#edc949",
        "#af7aa1",
        "#ff9da7",
        "#9c755f",
        "#bab0ab",
      ];
      let i = 0;
      let next_color = function() {
        let color = colors[i];
        i = (i + 1) % colors.length;
        return color;
      }

      cytoscape({
        container: document.getElementById('traffic'),

        elements: [
          // Nodes.
          {{range .Components}}
            {
              data: {
                id: '{{.Name}}',
                shortened: '{{shorten .Name}}',
                color: next_color(),
              },
            },
          {{end}}

          // Edges.
          {{range .Traffic}}
            {
              data: {
                id: '{{.Source}}-{{.Target}}',
                source: '{{.Source}}',
                target: '{{.Target}}',
                value: '{{.Value}}',
              },
            },
          {{end}}
        ],

        style: [
          {
            selector: 'node',
            style: {
              'background-color': (ele) => ele.data('color'),
              'label': (ele) => ele.data('shortened'),
            }
          },

          {
            selector: 'edge',
            style: {
              'label': (ele) => ele.data('value'),
              'width': (ele) => 50 * ele.data('value') / total_value,
              'line-color': '#ccc',
              'target-arrow-color': '#ccc',
              'target-arrow-shape': 'triangle',
              'curve-style': 'bezier'
            }
          }
        ],

        layout: {
          name: 'dagre', // dag-friendly layout
          rankDir: 'LR', // orient left to right
          rankSep: 200, // space between levels
          padding: 10, // padding around graph
        },
      });
    </script>
  </div>
</body>
</html>
